'''
Created on Feb 5, 2012

@author: jonathan
'''
import unittest
import random
from Controller import APIRequest

class TestParameter(object):
    
    ParameterClass = None

    def test_NoneName_RaiseValueError(self):
        with self.assertRaises(ValueError):
            self.ParameterClass(None)
        
    def test_EmptyName_RaiseValueError(self):
        with self.assertRaises(ValueError):
            self.ParameterClass("")
        
    def test_NumericStartedName_RaiseValueError(self):
        with self.assertRaises(ValueError):
            self.ParameterClass("0abcd")
        
    def test_UnderscoreStartedName_RaiseValueError(self):
        with self.assertRaises(ValueError):
            self.ParameterClass("__setitem__")
        
    def test_DotStartedName_RaiseValueError(self):
        with self.assertRaises(ValueError):
            self.ParameterClass(".attr")
            
    def test_ValidName_Unchanged(self):
        paramName = "Name52_90-j2"
        param = self.ParameterClass(paramName)
        self.assertEqual(param.name, paramName)
        
    def test_RequiredTrue_RequiredSetToTrue(self):
        param = self.ParameterClass("test", required=True)
        self.assertTrue(param.required)
        
    def test_RequiredFalse_RequiredSetToFalse(self):
        param = self.ParameterClass("test", required=False)
        self.assertFalse(param.required)
        
    def test_RequiredNone_RequiredSetToFalse(self):
        param = self.ParameterClass("test", required=None)
        self.assertFalse(param.required)
            
    def test_RequiredString_RequiredSetToTrue(self):
        param = self.ParameterClass("test", required="true")
        self.assertTrue(param.required)
        
    def test_RequiredEmptyString_RequiredSetToFalse(self):
        param = self.ParameterClass("test", required="")
        self.assertFalse(param.required)
            
    def test_RequiredList_RequiredSetToTrue(self):
        param = self.ParameterClass("test", required=["true"])
        self.assertTrue(param.required)
        
    def test_RequiredEmptyList_RequiredSetToFalse(self):
        param = self.ParameterClass("test", required=[])
        self.assertFalse(param.required)
            
    def test_RequiredZero_RequiredSetToFalse(self):
        param = self.ParameterClass("test", required=0)
        self.assertFalse(param.required)
        
    def test_RequiredOne_RequiredSetToTrue(self):
        param = self.ParameterClass("test", required=1)
        self.assertTrue(param.required)
        
    def test_ValidateNone_ReturnNone(self):
        param = self.ParameterClass("test")
        self.assertEqual(param.Validate(None), None)
        
    def test_DefaultNone_DefaultSetToNone(self):
        param = self.ParameterClass("test", default=None)
        self.assertEqual(param.default, None)
        
class TestInteger(TestParameter):
    
    UPPER_BOUND = None
    LOWER_BOUND = None
    
    def test_LTLowerBound_RaiseParameterLoadError(self):
        param = self.ParameterClass("test")
        with self.assertRaises(APIRequest.ParameterLoadError):
            param.Validate(self.LOWER_BOUND - 1)
        
    def test_LowerBound_ReturnsLowerBound(self):
        param = self.ParameterClass("test")
        self.assertEqual(self.LOWER_BOUND, param.Validate(self.LOWER_BOUND))
        
    def test_UpperBound_ReturnsUpperBound(self):
        param = self.ParameterClass("test")
        self.assertEqual(self.UPPER_BOUND, param.Validate(self.UPPER_BOUND))
        
    def test_GTUpperBound_RaiseParameterLoadError(self):
        param = self.ParameterClass("test")
        with self.assertRaises(APIRequest.ParameterLoadError):
            param.Validate(self.UPPER_BOUND + 1)
        
    def test_BetweenUpperAndLowerBounds_ReturnValue(self):
        param = self.ParameterClass("test")
        value = random.randint(self.LOWER_BOUND, self.UPPER_BOUND)
        self.assertEqual(value, param.Validate(value))
        
    def test_IntegerString_ReturnIntegerValue(self):
        param = self.ParameterClass("test")
        value = random.randint(self.LOWER_BOUND, self.UPPER_BOUND)
        self.assertEqual(value, param.Validate(str(value)))
        
    def test_NonIntegerString_RaiseParameterLoadError(self):
        param = self.ParameterClass("test")
        with self.assertRaises(APIRequest.ParameterLoadError):
            param.Validate("")
            
    def test_List_RaiseParameterLoadError(self):
        param = self.ParameterClass("test")
        with self.assertRaises(APIRequest.ParameterLoadError):
            param.Validate([])
        
    def test_DefaultLTLowerBound_RaiseValueError(self):
        with self.assertRaises(ValueError):
            self.ParameterClass("test", default=self.LOWER_BOUND - 1)
            
    def test_DefaultLowerBound_DefaultSetToLowerBound(self):
        param = self.ParameterClass("test", default=self.LOWER_BOUND)
        self.assertEqual(param.default, self.LOWER_BOUND)
        
    def test_DefaultUpperBound_DefaultSetToUpperBound(self):
        param = self.ParameterClass("test", default=self.UPPER_BOUND)
        self.assertEqual(param.default, self.UPPER_BOUND)
        
    def test_DefaultGTUpperBound_RaiseValueError(self):
        with self.assertRaises(ValueError):
            self.ParameterClass("test", default=self.UPPER_BOUND + 1)
    
    def test_DefaultBetweenUpperAndLower_DefaultSetToValue(self):
        value = random.randint(self.LOWER_BOUND, self.UPPER_BOUND)
        param = self.ParameterClass("test", default=value)
        self.assertEqual(param.default, value)
        
    def test_DefaultIntegerString_DefaultSetToInteverValue(self):
        value = random.randint(self.LOWER_BOUND, self.UPPER_BOUND)
        param = self.ParameterClass("test", default=str(value))
        self.assertEqual(param.default, value)
        
    def test_DefaultNonIntegerString_RaiseValueError(self):
        with self.assertRaises(ValueError):
            self.ParameterClass("test", default="")
    
    def test_DefaultList_RaiseValueError(self):
        with self.assertRaises(ValueError):
            self.ParameterClass("test", default=[])
        
class TestInteger32(unittest.TestCase, TestInteger):
    
    ParameterClass = APIRequest.Integer32
    UPPER_BOUND = 2147483647
    LOWER_BOUND = -2147483648
    
class TestUnsignedInteger32(unittest.TestCase, TestInteger):
    
    ParameterClass = APIRequest.UnsignedInteger32
    UPPER_BOUND = 4294967295
    LOWER_BOUND = 0
    
class TestInteger64(unittest.TestCase, TestInteger):
    
    ParameterClass = APIRequest.Integer64
    UPPER_BOUND = 9223372036854775807
    LOWER_BOUND = -9223372036854775808
    
class TestUnsignedInteger64(unittest.TestCase, TestInteger):
    
    ParameterClass = APIRequest.UnsignedInteger64
    UPPER_BOUND = 18446744073709551615
    LOWER_BOUND = 0

class TestString(unittest.TestCase, TestParameter):
    
    ParameterClass = APIRequest.String
    
    def test_None_ReturnNone(self):
        param = self.ParameterClass("test")
        self.assertEqual(param.Validate(None), None)
        
    def test_EmptyString_ReturnEmptyString(self):
        param = self.ParameterClass("test")
        self.assertEqual(param.Validate(""), "")
        
    def test_Number_ReturnStringRepresentation(self):
        param = self.ParameterClass("test")
        self.assertEqual(param.Validate(5), "5")
        
    def test_DefaultNone_DefaultSetToNone(self):
        param = self.ParameterClass("test", default=None)
        self.assertEqual(param.default, None)
        
    def test_DefaultEmptyString_DefaultSetToEmptyString(self):
        param = self.ParameterClass("test", default="")
        self.assertEqual(param.default, "")
        
    def test_DefaultNumber_DefaultSetToStringRepresentation(self):
        param = self.ParameterClass("test", default=5)
        self.assertEqual(param.default, "5")

if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()